Documentation for Users  1.3.1
Perception Toolbox for Virtual Reality (PTVR) Manual
visual_search.py
Go to the documentation of this file.
1 # -*- coding: utf-8 -*-
2 
3 '''
4 ...\PTVR_Researchers\Python_Scripts\Experiments\visual_search.py
5 '''
6 from PTVR.Visual import The3DWorld# Used to create the experiment
7 from PTVR.SystemUtils import LaunchThe3DWorld # Used to launch the experiment
8 from PTVR.Stimuli.Scenes import VisualScene, CheckScene # Used to create the scene
9 from PTVR.Stimuli.Objects import Cube, Sphere, AudioSource # Used to create visual object
10 from PTVR.Stimuli.Color import RGBColor
11 from PTVR.Data.Event import PointedAt, HandController
12 from PTVR.Data.Callback import AddInteractionPassedToCallback, EndCurrentScene,ChangeObjectOutline,ChangeAudioSettings
13 from PTVR.Pointing.PointingCursor import PointingLaser, LaserContingency
14 from numpy import array
15 import random
16 
17 
18 # =============================================================================
19 # PARAMETERS #
20 # =============================================================================
21 username = "Henry" # The subject's name
22 height_of_head = 1.2 # this value (in meters) is chosen so as to correspond
23 # to the height of the subject's headset during the experiment (seated or standing)
24 viewpoint_position = array ([0, height_of_head, 0])
25 # Recall: a viewpoint is the origin of the current CS used to draw
26 # the stimuli to be "seen" from this viewpoint
27 
28 
29 
30 number_of_distractor = 512
31 
32 radial_distance_min_max_values = array([2, 15])
33 
34 # Color VisualSearch
35 color_base = RGBColor(r=0, g=1, b=0) # Green
36 color_distractor = RGBColor(r=1, g=0, b=0) # Red
37 color_target = RGBColor(r=1, g=0, b=0) # Red
38 
39 
40 my_laser_color = RGBColor(r= 0.7)
41 hand = LaserContingency.RIGHT_HAND
42 
43 
44 
45 # =============================================================================
46 # END PARAMETERS #
47 # =============================================================================
48 my_world = The3DWorld()
49 sound_end_of_block = "applaudisement.mp3" # sound indicating end of block
50 sound_wrong_response = "buzzer.ogg"
51 handcontroller_id = my_world.handControllerRight.id
52 configurations_set = set()
53 
54 def new_objects(random_value):
55  if(random_value == 1):
56  value = random.randint (0, 1)
57  if(value == 1):
58  color_object = color_base
59  else:
60  color_object = color_distractor
61 
62  my_object = Sphere(size_in_meters= array([0.2, 0.2, 0.2]), color = color_object)
63  else:
64  my_object = Cube(size_in_meters= array([0.2, 0.2, 0.2]), color = color_base)
65  return my_object
66 
68  reticle_pointing_at_object = PointedAt (target_id = my_object.id,
69  activation_cone_origin_id=handcontroller_id,
70  activation_cone_radius_deg=1, activation_cone_depth=500, mode="press",
71  event_name="object_is_pointed_at")
72  reticle_NOT_pointing_at_object = PointedAt (target_id = my_object.id,
73  activation_cone_origin_id=handcontroller_id,
74  activation_cone_radius_deg=1, activation_cone_depth=500, mode="release",
75  event_name="object_is_not_pointed_at")
76  return reticle_pointing_at_object, reticle_NOT_pointing_at_object
77 
79  callback_outline_on = ChangeObjectOutline(object_id=my_object.id, outline_color=RGBColor(r=1.0,g= 1.0, b=1.0,a= 1),
80  effect="activate")
81  callback_outline_off = ChangeObjectOutline(object_id=my_object.id, outline_color=RGBColor(r=1.0,g= 1.0, b=1.0,a= 1),
82  effect="deactivate")
83  return callback_outline_on,callback_outline_off
84 
85 def main():
86  print("Creating an experiment to study visual search in various 3D regions...")
87 
88  my_initial_scene = CheckScene ( my_world = my_world,
89  are_both_hand_controllers_visible= True,
90  text_information = "In this experiment you have "\
91  "to search for the red cube \n among over objects " \
92  "by pointing at it and pressing the trigger.\n" \
93  "When you are ready to start, please press the trigger.")
94  my_world.add_scene (my_initial_scene)
95 
96  # Create the visual scene that will contain the distractors and the target
97  my_scene = VisualScene (is_right_hand_controller_visible = True)
98 
99  # Create a pointer
100  my_laser_beam = PointingLaser ( hand_laser = hand,
101  laser_color = my_laser_color,
102  laser_width = 0.01 )
103  my_scene.place_pointing_laser ( my_laser_beam )
104  my_scene.AddPointingCursor(my_laser_beam)
105 
106 
107  my_world.translate_coordinate_system_along_current(translation = viewpoint_position)
108 
109  audio_wrong = AudioSource(audioFile=sound_wrong_response, is_playing_directly=False)
110  my_scene.place(audio_wrong,my_world)
111  while len(configurations_set) < number_of_distractor+1:
112 
113  radialdistance = random.uniform(radial_distance_min_max_values [0],
114  radial_distance_min_max_values [1])
115  eccentricity = random.gauss(90, 40)
116  halfmeridian = random.randint(0, 360)
117  configuration = (radialdistance, eccentricity, halfmeridian)
118  if tuple(configuration) not in configurations_set:
119  configurations_set.add(tuple(configuration))
120 
121  configurations = [list(config) for config in configurations_set]
122  target_configuration = random.choice(configurations)
123  print("my target is at np.array([radial_distance,eccentricity,half_meridian)) : " +
124  str(target_configuration))
125  for config in configurations:
126  radialdistance = config[0]
127  eccentricity = config[1]
128  halfmeridian = config[2]
129  if(config != target_configuration):
130  my_object = new_objects(random.randint(0, 1)) # Sphere or Cube
131  else:
132  my_object = Cube(size_in_meters= array([0.2, 0.2, 0.2]), color=color_target)
133  my_object.set_perimetric_coordinates(radialDistance=radialdistance,
134  eccentricity=eccentricity, halfMeridian=halfmeridian)
135  my_scene.place(my_object, my_world)
136  inside,outside = create_events_when_pointing_at_objects (my_object)
137  outline_on,outline_off = create_callbacks_to_change_objects(my_object)
138  launchwrong_song = ChangeAudioSettings(audio_id=audio_wrong.id)
139  press = HandController(valid_responses=['right_trigger'],mode="press",event_name="press")
140  if(config != target_configuration):
141  add = AddInteractionPassedToCallback(events=[press], callbacks=[launchwrong_song],
142  effect="activate")
143  remove = AddInteractionPassedToCallback(events=[press], callbacks=[launchwrong_song],
144  effect="deactivate")
145  my_scene.AddInteraction(events=[inside], callbacks=[add,outline_on])
146  my_scene.AddInteraction(events=[outside], callbacks=[remove,outline_off])
147 
148  else:
149  finish = EndCurrentScene(callback_name = "target has been found")
150 
151  add = AddInteractionPassedToCallback(events=[press], callbacks=[finish], effect="activate")
152  remove = AddInteractionPassedToCallback(events=[press], callbacks=[finish], effect="deactivate")
153  # Register Events and Callbacks
154  my_scene.AddInteraction(events=[inside], callbacks=[add,outline_on])
155  my_scene.AddInteraction(events=[outside], callbacks=[remove,outline_off])
156 
157 
158  my_world.add_scene(my_scene)
159 
160  my_world.reset_coordinate_system()
161 
162  calibration = CheckScene(my_world = my_world,text_information= "Congratulations!",are_both_hand_controllers_visible = True)
163  audio = AudioSource(audioFile=sound_end_of_block)
164  calibration.place(audio,my_world)
165  my_world.add_scene(calibration)
166 
167  my_world.write() # create json file containing the parameters of the present experiment
168  print("The .json file corresponding to this experiment has been created.")
169 
170 
171 if __name__ == "__main__":
172  main()
173  LaunchThe3DWorld(username) # Launch the3DWorld with PTVR.
def LaunchThe3DWorld(jsonFileCategory="Externals")
Definition: SystemUtils.py:182
def new_objects(random_value)
def create_events_when_pointing_at_objects(my_object)
def create_callbacks_to_change_objects(my_object)